﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Tycho.Runtime;
using System.Windows.Data;

namespace Tycho.Peyote {
    /// <summary>
    /// Interaction logic for GlyphHandle.xaml
    /// </summary>
    public partial class GlyphHandle : UserControl {
        private readonly Environment Environment;
        private AnyObject InternalRuntimeName;
        public bool InOptionsMode { get; set; }
        public GlyphControl PresentationGlyph { get; private set; }
        public GlyphControl OptionsGlyph { get; private set; }

        public bool ShowReevaluate {
            get {
                return PresentationGlyph.RefreshType == GlyphRefreshType.Manual;
            }
        }

        public Brush HandleBackground {
            get {
                switch (PresentationGlyph.RefreshType) {
                    case GlyphRefreshType.Automatic:
                        return (Brush) Resources["RefreshAutomaticBrush"];
                    case GlyphRefreshType.Manual:
                        return (Brush) Resources["RefreshManualBrush"];
                    case GlyphRefreshType.None:
                    default:
                        return (Brush) Resources["RefreshNoneBrush"];
                }
            }
        }

        public GlyphHandle (GlyphControl presentationControl, GlyphControl optionsControl, Environment environment) {
            InitializeComponent ();

            DataContext = this;

            Environment = environment;

            PresentationGlyph = presentationControl;
            PresentationGlyph.GlyphHandle = this;

            OptionsGlyph = optionsControl;
            OptionsGlyph.GlyphHandle = this;
            OptionsGlyph.DataContext = this;

            new DragDropHandler (Handle, new DataObject (this));

            HandlePopup.CustomPopupPlacementCallback = CustomPopupPlacementCallback;
            SizeChanged += GlyphHandle_SizeChanged;
        }

        void GlyphHandle_SizeChanged (object sender, SizeChangedEventArgs e) {
            HandlePopup.PopupAnimation = PopupAnimation.None;
            HandlePopup.IsOpen = false;
            HandlePopup.IsOpen = true;
            HandlePopup.PopupAnimation = PopupAnimation.Fade;
        }

        private CustomPopupPlacement[] CustomPopupPlacementCallback (Size size, Size targetSize, Point offset) {
            CustomPopupPlacement topLeft = new CustomPopupPlacement (new Point (0, -size.Height), PopupPrimaryAxis.Horizontal);
            CustomPopupPlacement bottomLeft = new CustomPopupPlacement (new Point (0, targetSize.Height), PopupPrimaryAxis.Horizontal);

            return new [] {bottomLeft, topLeft};
        }

        public AnyObject RuntimeName {
            get {
                return InternalRuntimeName;
            }
            set {
                Environment.Transaction (() => {
                    Environment.TopLevel[value] = PresentationGlyph.RuntimeValue;
                });
                InternalRuntimeName = value;
            }
        }

        private void UserControl_MouseEnter (object sender, MouseEventArgs e) {
            HandlePopup.BeginAnimation (Popup.IsOpenProperty, null);
            HandlePopup.IsOpen = true;
        }

        private void UserControl_MouseLeave (object sender, MouseEventArgs e) {
            BooleanAnimationUsingKeyFrames delayClose = new BooleanAnimationUsingKeyFrames ();
            delayClose.KeyFrames.Add (new DiscreteBooleanKeyFrame(false, KeyTime.FromTimeSpan (new TimeSpan(0, 0, 0, 0, 500))));
            HandlePopup.BeginAnimation (Popup.IsOpenProperty, delayClose);
        }

        private void RemoveButton_Click (object sender, RoutedEventArgs e) {
            Environment.Layout.RemoveGlyph (this);
        }

        private void ReevaluateButton_Click (object sender, RoutedEventArgs e) {
            PresentationGlyph.Reevaluate ();
        }
    }

    class SizeToRectConverter : IValueConverter {
        public object Convert (object value, Type targetType, object parameter, CultureInfo culture) {
            Size size = (Size) value;
            return new Rect (size);
        }

        public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture) {
            throw new System.NotImplementedException ();
        }
    }
}
